<?php
namespace app\mini_api\controller;
use think\Db;

class Pay extends Permission
// class Pay extends ApiDev
{
    public function _initialize()
    {
        parent::_initialize();
        parent::check();
    }
    public function index()
    {
        $map = [
            'id' => $this->input_data['id']
        ];
        if(! $goods = db('Goods')->where($map)->find() ) $this->resErr('未找到对应商品');

        # 通过code获取当前微信用户的openid
        $url = "https://api.weixin.qq.com/sns/jscode2session";
        // 参数
        $params['appid']= 'wx82ee966ac67ed2a7';
        $params['secret']= '18767b4f343d5620f05ad786af007534';
        $params['js_code']= input('post.code');
        $params['grant_type']= 'authorization_code';        

        # 微信API返回的session_key 和 openid
        $arr = httpCurl($url, $params, 'GET');
        $arr = json_decode($arr,true);

        # 判断是否成功
        if(isset($arr['errcode']) && !empty($arr['errcode'])) $this->resErr($arr['errmsg']); 

        $openid = $arr['openid'];
        // $openid = 'oeQu35VKNMqxAeuXzIFtUM5nQREs';

        // oeQu35VKNMqxAeuXzIFtUM5nQREs
        # 创建订单
        $trade_no = $this->_create_trade_no();
        $data = [
            'type' => $goods['type'],
            'goods_id' => $goods['id'],
            'price' => $goods['price'],
            'member_id' => $this->user['id'],
            'out_trade_no' => $trade_no,
            'title' => $goods['title'].' '.$goods['subtitle'],
            'contract' => $this->input_data['content']
        ];
        db('Trade')->insert($data);

        // $goods['price'] = 1;
        $this->payWithWechat($goods['price'],$goods['title'],$trade_no,$openid);
    }


    // 微信支付
    private function payWithWechat($price,$body,$trade_no,$openid)
    {
        $this->_wxPay($price,$body,$trade_no,$openid);
        
    }
    private function _wxPay($price,$body,$trade_no,$openid)
    {
        

        $params = [
            'appid' => 'wx82ee966ac67ed2a7', // 小程序
            'body' => $body,
            'mch_id' => '1646997329', //商户号
            'nonce_str' => $this->createNoncestr(), //随机字符串
            'out_trade_no' => $trade_no, //订单号
            'openid' => $openid,
            'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
            // 'spbill_create_ip' => '117.182.132.82',
            'total_fee' => $price,
            // 'total_fee' => 1,
            'attach' => '',
            'trade_type' => 'JSAPI',
            'notify_url' => 'https://ycapi.lw81888.com/mini_api/wx_pay_notify/payCallback'
        ];

        // 按照要求计算sign
        $sign = $this->sign($params);
        $params['sign'] = $sign;

        $xml = $this->xml($params);


        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $output = $this->http_request($url,$xml);
        if (false === $output) {
        echo 'CURL Error:' . curl_error($ch);
        }

        // 下单成功的话，微信返回个XML，里面包含prepayID，提取出来

        if (0 === preg_match('/<prepay_id><\!\[CDATA\[(\w+)\]\]><\/prepay_id>/', $output, $match)) {
        echo $output;
        exit(0);
        }

        // 这里不是给小程序返回个prepayID，而是返回一个包含其他字段的JSON
        // 这个JSON小程序自己也可以生成，放在服务端生成是出于两个考虑：
        // 
        // 1. 小程序的appid不用写在小程序的代码里，appid、secret信息全部由服务器管理，比较安全
        // 2. 计算paySign需要用到md5，小程序端使用的是JavaScript，没有内置的md5函数，放在服务端计算md5比较方便

        $prepayId = $match[1];
        $response= [
        'appId' => 'wx82ee966ac67ed2a7',
        // 随机串，32个字符以内
        'nonceStr' => $this->createNoncestr(),
        // 微信规定
        'package' => 'prepay_id=' . $prepayId,
        'signType' => 'MD5',
        // 时间戳，注意得是字符串形式的
        'timeStamp' => (string) time(),
        ];

        // $sequence = '';
        // foreach ($response as $key => $value) {
        // $sequence .= "$key=$value&";
        // }
        $paySign = $this->sign($response);

        $response['paySign'] = $paySign;

        $this->resSuc($response);
        // echo json_encode($response);

    }


    private function sign($data)
    {
        $key = '20232a613b1y9b54c46734ed48bbced5';
        //签名步骤一：按字典序排序参数
        ksort($data);
        $buff = '';
        foreach ($data as $k => $v) {
            if($k != 'sign' && $v != '' && !is_array($v)){
                $buff .= $k . '=' . $v . '&';
            }
        }
        $buff = trim($buff,'&');

        //签名步骤二：在string后加入KEY
        $string = $buff . "&key=".$key;

        //签名步骤三：MD5加密或者HMAC-SHA256
        $string = md5($string);
        
        //签名步骤四：所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }

    private function createNoncestr($length = 32) {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    private function xml($data)
    {
        ksort($data);

        $data_xml = '<xml>';


        foreach ($data as $key => $val) {
            
            $data_xml.="<".$key.">".$val."</".$key.">";
            
        }




        $data_xml .= '</xml>';
        return $data_xml;
    }



    private function http_request($url,$rawData)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $rawData);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type:text']);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }

    private function getxml($xml)
    {
        $p = xml_parser_create();
        xml_parse_into_struct($p, $xml, $vals, $index);
        xml_parser_free($p);
        $data = '';
        foreach ($index as $k => $v) {
            if($k = 'xml' || $k == 'XML') continue;
            $tag = $vals[$v[0]]['tag'];
            $v = $vals[$v[0]]['value'];
            $data[$tag] = $v;
        }
        return $data;
    }

    // 获取代理的提成点数
    private function getAgentCommission($id)
    {
        $map['id'] = $id;
        $user = db('User')->where($map)->find();
        $data = [
            'auction' => $user['agent_commission_auction'],
            'trade' => $user['agent_commission_trade'],
        ];
    }

    // 创建订单号
    private function _create_trade_no()
    {
        $date = date('Ymd');
        $rand = rand(11111,99999);

        $map['out_trade_no'] = $date.$rand;
        if (db('Trade')->where($map)->find() ) $this->create_trade_no();

        return $map['out_trade_no'];
    }

}
